package com.zwh.modules.controller;

import java.io.IOException;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

/**
 * @author zwh
 * @date 2021/7/9 13:18
 **/
@RestController
public class DiscoveryController {

    @Autowired
    private RestTemplate restTemplate;
    @Autowired
    private DiscoveryClient discoveryClient;


    /**
     * 获取服务名对应的（ip+port）列表
     * @param serviceName
     * @return
     */
    @GetMapping("/discovery/{serviceName}")
    public ResponseEntity<List<String>> discovery(@PathVariable String serviceName){
        /**
         * 通过服务的ID或者名称得到服务的实例列表
         */
        List<ServiceInstance> instances = discoveryClient.getInstances(serviceName);

        if (instances==null||instances.isEmpty()){
            return ResponseEntity.notFound().build();
        }
        List<String> service = new ArrayList<>(instances.size());
        instances.forEach(instance->{
            service.add(instance.getHost()+":"+instance.getPort());
            ;        });
        return ResponseEntity.ok(service);
    }

    /**
     * 手动调用http服务
     * @param message
     * @return
     */
    @GetMapping("/rpcv1/{message}")
    public ResponseEntity<String> rpcv1(@PathVariable("message") String message)  {
        CloseableHttpClient httpClient = HttpClientBuilder.create().build();
        HttpGet httpRequest = new HttpGet(MessageFormat.format("http://localhost:8081/echo/{0}",message));
        String result = null;
        try {
            HttpResponse response = httpClient.execute(httpRequest);
            HttpEntity entity = null;
            try {
                if(response.getStatusLine().getStatusCode() == HttpStatus.OK.value()){
                    entity = response.getEntity();
                    result = EntityUtils.toString(entity, "UTF-8");
                    return ResponseEntity.ok(String.format("远程调用成功，结果为"+result));
                }

            } finally {
                EntityUtils.consume(entity);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                httpClient.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return ResponseEntity.ok("远程调用失败");

    }

    /**
     * 服务发现获取服务实例，再进行手动调用http服务 http://ip：port访问
     * @param message
     * @return
     */
    @GetMapping("/rpcv2/{message}")
    public ResponseEntity<String> rpcv2(@PathVariable("message") String message){
        List<ServiceInstance> instances = discoveryClient.getInstances("service-provider");
        if (instances==null||instances.isEmpty()){
            return ResponseEntity.badRequest().body("当前服务没有服务的提供者");
        }
        ServiceInstance serviceInstance = instances.get(0);
        String instace=serviceInstance.getHost()+":"+serviceInstance.getPort();
        ResponseEntity<String> responseEntity = restTemplate.getForEntity(
                String.format("http://%s/echo/{message}",instace),
                String.class,
                message);
        if(responseEntity.getStatusCode()== HttpStatus.OK){
            return ResponseEntity.ok(String.format("远程调用成功，结果为"+responseEntity.getBody()));
        }
        return ResponseEntity.badRequest().body("远程调用失败");
    }

    /**
     * 手写负载均衡算法
     * @param message
     * @return
     */
    @GetMapping("/rpcv3/{message}")
    public ResponseEntity<String> rpcv3(@PathVariable("message") String message){
        List<ServiceInstance> instances = discoveryClient.getInstances("service-provider");
        if (instances==null||instances.isEmpty()){
            return ResponseEntity.badRequest().body("当前服务没有服务的提供者");
        }
        ServiceInstance serviceInstance = loadBalanced(instances);
        String instace=serviceInstance.getHost()+":"+serviceInstance.getPort();
        ResponseEntity<String> responseEntity = restTemplate.getForEntity(
                String.format("http://%s/echo/{message}",instace),
                String.class,
                message);
        if(responseEntity.getStatusCode()== HttpStatus.OK){
            return ResponseEntity.ok(String.format("远程调用成功，结果为"+responseEntity.getBody()));
        }
        return ResponseEntity.badRequest().body("远程调用失败");
    }

    /**
     * 从一个服务的实例列表里面选择一个服务的列表
     * @param instances 实例列表
     * @return 具体的实例
     */
    private ServiceInstance loadBalanced(List<ServiceInstance> instances) {
        Random random=new Random(System.currentTimeMillis());
        return instances.get(random.nextInt(instances.size()));
    }
    /**
     * 调用nacos的负载均衡算法
     * @param message
     * @return
     */
    @GetMapping("/rpcv4/{message}")
    public ResponseEntity<String> rpcv4(@PathVariable("message") String message){
        ResponseEntity<String> responseEntity = restTemplate.getForEntity(
                "http://service-provider/echo/{message}",
                String.class,
                message);
        if(responseEntity.getStatusCode()== HttpStatus.OK){
            return ResponseEntity.ok(String.format("远程调用成功，结果为"+responseEntity.getBody()));
        }
        return ResponseEntity.badRequest().body("远程调用失败");
    }


}
